//圆形Image扩展组件，支持圆形碰撞检测
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

namespace BToolkit
{
    [AddComponentMenu("UI/PolygonImage")]
    public class PolygonImage : Image
    {
        public RectTransform[] points = new RectTransform[4];
        public float texScale = 1;

        private Vector2[] poses = new Vector2[0];

        void Update()
        {
            if (poses.Length != points.Length) poses = new Vector2[points.Length];
            for (int i = 0; i < points.Length; i++)
            {
                RectTransform point = points[i];
                if (point && poses[i] != point.anchoredPosition)
                {
                    poses[i] = point.anchoredPosition;
                    this.SetAllDirty();
                    RefreshSizeDelta();
                }
            }
        }

        protected override void OnPopulateMesh(VertexHelper vh)
        {
            vh.Clear();

            Vector2 size = rectTransform.sizeDelta;
            Vector2 pivot = rectTransform.pivot;
            //圆心
            Vector2 centerUV = Vector2.zero;
            Vector2 centerPos = Vector2.zero;
            centerPos.x += size.x * (0.5f - pivot.x);
            centerPos.y += size.y * (0.5f - pivot.y);
            AddVertex(vh, centerPos, centerUV, size);
            //外圈
            bool isAllReady = true;
            for (int i = 0; i < points.Length; i++)
            {
                if (!points[i])
                {
                    isAllReady = false;
                    break;
                }
            }
            if (isAllReady)
            {
                for (int i = 0; i < points.Length; i++)
                {
                    Vector2 uv = points[i].anchoredPosition;
                    Vector2 pos;
                    pos.x = uv.x + size.x * (0.5f - pivot.x);
                    pos.y = uv.y + size.y * (0.5f - pivot.y);
                    AddVertex(vh, pos, uv, size);
                }
                AddTriangle(vh, points.Length);
            }
        }

        /// <summary>
        /// 添加顶点数据
        /// </summary>
        private void AddVertex(VertexHelper vh, Vector2 pos, Vector2 uv, Vector2 size)
        {
            UIVertex vertex = UIVertex.simpleVert;
            vertex.color = color;
            vertex.position = pos;
            Vector2 uv0 = new Vector2((uv.x + size.x * 0.5f) / size.x, (uv.y + size.y * 0.5f) / size.y);

            //支持贴图缩放
            uv0 *= texScale;
            uv0 -= Vector2.one * (texScale - 1f) * 0.5f;

            vertex.uv0 = uv0;
            vh.AddVert(vertex);
        }

        void AddTriangle(VertexHelper vh, int count)
        {
            for (int i = 1; i <= count; i++)
            {
                if (i < count)
                {
                    vh.AddTriangle(0, i, i + 1);
                }
                else
                {
                    vh.AddTriangle(0, i, 1);
                }
            }
        }

        void RefreshSizeDelta()
        {
            float maxX = 0;
            float maxY = 0;
            for (int i = 0; i < points.Length; i++)
            {
                RectTransform point = points[i];
                if (point)
                {
                    if (Mathf.Abs(point.anchoredPosition.x) > maxX)
                    {
                        maxX = Mathf.Abs(point.anchoredPosition.x);
                    }
                    if (Mathf.Abs(point.anchoredPosition.y) > maxY)
                    {
                        maxY = Mathf.Abs(point.anchoredPosition.y);
                    }
                }
            }
            rectTransform.sizeDelta = new Vector2(maxX * 2, maxY * 2);
        }

        //重写点击判断
        public override bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera)
        {
            //用所有连线判断相交次数的奇偶来判断是否点击在图形内
            Vector2 clickPos;
            RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPoint, eventCamera, out clickPos);
            return IsInPolygon(clickPos, poses);
        }

        bool IsInPolygon(Vector2 point, Vector2[] polygonPoints)
        {
            bool inside = false;
            int pointCount = polygonPoints.Length;
            Vector2 p1, p2;
            for (int i = 0, j = pointCount - 1; i < pointCount; j = i, i++)
            {
                p1 = polygonPoints[i];
                p2 = polygonPoints[j];
                if (point.y < p2.y)
                {
                    if (p1.y <= point.y)
                    {
                        if ((point.y - p1.y) * (p2.x - p1.x) > (point.x - p1.x) * (p2.y - p1.y))
                        {
                            inside = (!inside);
                        }
                    }
                }
                else if (point.y < p1.y)
                {
                    if ((point.y - p1.y) * (p2.x - p1.x) < (point.x - p1.x) * (p2.y - p1.y))
                    {
                        inside = (!inside);
                    }
                }
            }
            return inside;
        }

#if UNITY_EDITOR
        [UnityEditor.MenuItem("GameObject/UI/Polygon Image")]
        static void Create()
        {
            GameObject go = new GameObject("PolygonImage");
            go.transform.SetParent(UnityEditor.Selection.activeGameObject.transform, false);
            PolygonImage image = go.AddComponent<PolygonImage>();
            image.points = new RectTransform[3];
            for (int i = 0; i < image.points.Length; i++)
            {
                GameObject bar = new GameObject("Bar" + i);
                bar.transform.SetParent(go.transform, false);
                RectTransform rectTransform = bar.AddComponent<RectTransform>();
                rectTransform.sizeDelta = Vector2.zero;
                image.points[i] = rectTransform;
            }
            image.points[0].anchoredPosition = new Vector2(0, 50);
            image.points[1].anchoredPosition = new Vector2(50, -50);
            image.points[2].anchoredPosition = new Vector2(-50, -50);
        }
#endif

    }

}